package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.UltimusConstants;
import ae.pcfc.cldos.online.common.UltimusConstants.ApplicationResubmitDecision;
import ae.pcfc.cldos.online.common.UltimusConstants.EmployeeType;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.EmploymentVisaCancel;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ReviewComments;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TaskMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TempFileStorage;
import ae.pcfc.cldos.online.common.clddb.domain.manager.EmploymentVisaCancelDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.InvalidEmpIdException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.facade.BaseProcesesFacade;
import ae.pcfc.cldos.online.common.facade.EmploymentVisaCancelationFacade;
import ae.pcfc.cldos.online.common.factories.AppMetaDataFactory;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.FileVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.ev.ren.can.EmploymentVisaCancelationDetailsVO;
import ae.pcfc.cldos.online.common.vo.ev.ren.can.EmploymentVisaCancelationVO;
import ae.pcfc.cldos.online.common.vo.ev.ren.can.SubmitExitPaperVO;
import ae.pcfc.cldos.online.common.vo.fnp.FNPPaymentAdviceVO;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.wf.ConstantsWF;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.EmploymentVisaCancelationAppInfoVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.BaseGVariablesVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.LaunchIncedentVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.TerminateEVReSubmGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.TerminateEVSubmGVarVO;

/**
 * 
 * @author arosa
 *
 */
public class EmploymentVisaCancelationFacadeImpl extends BaseProcesesFacade implements EmploymentVisaCancelationFacade {

	private EmploymentVisaCancelDOM employmentVisaCancelDOM;
	
	public void setEmploymentVisaCancelDOM(
			EmploymentVisaCancelDOM employmentVisaCancelDOM) {
		this.employmentVisaCancelDOM = employmentVisaCancelDOM;
	}
	
	@Transactional
	public EmploymentVisaCancelationVO getEmploymentVisaCancelationAppInfo(String appId, UserVO userVO, Steps step) throws BadAppException{
		
		EmploymentVisaCancelationVO employmentVisaCancelationVO = new EmploymentVisaCancelationVO();
		
		
		AppMetaData appMetaData = null;
		
		if(userVO.isGeneralAdmin()){
			appMetaData = appMetaDataDOM
				.getAppMetaDataByIdForGeneralAdmin(appId, Process.PROCESS_EMPLOYMENT_VISA_CANCELATION, step);
		} else {
			User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
			appMetaData = appMetaDataDOM
					.getAppMetaDataById(appId, Process.PROCESS_EMPLOYMENT_VISA_CANCELATION, step, user.getClientId());
		}
		EmploymentVisaCancelationDetailsVO employmentVisaCancelationDetailsVO = 
				new EmploymentVisaCancelationDetailsVO();
		getMapper().map(appMetaData.getEmploymentVisaCancel(), employmentVisaCancelationDetailsVO);
		employmentVisaCancelationVO.setEmploymentVisaCancelationDetailsVO(employmentVisaCancelationDetailsVO);
		employmentVisaCancelationVO.setClientReferenceNo(appMetaData.getClientRefNo());
		employmentVisaCancelationVO.setInitiatedBy(appMetaData.getWfInitiatedBy());
		
		List<TempFileStorage> tempFileStoragesList = appMetaData.getTempFileStorages();
		List<FileVO> fileVOList = new ArrayList<FileVO>(tempFileStoragesList.size());
		for(TempFileStorage tempFileStorage : tempFileStoragesList){
			FileVO fileVO = new FileVO();
			getMapper().map(tempFileStorage, fileVO);
			fileVOList.add(fileVO);
		}
		employmentVisaCancelationVO.setFileVOList(fileVOList);
		employmentVisaCancelationVO.setApplicationCommentVOs(getCommentsVOList(appMetaData.getReviewComments()));
		try{
			employmentVisaCancelationVO.setWfStatus(gsInfoManager.getWfStatus(employmentVisaCancelationVO.getClientReferenceNo()));
		}catch(Exception e){
			employmentVisaCancelationVO.setWfStatus(ConstantsGS.EMP_STATUS_NA);
		}
		return employmentVisaCancelationVO;
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO submit(EmploymentVisaCancelationVO employeVisaCancelationVO) throws Exception{
		return storeToDb(employeVisaCancelationVO, null, false);
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO reSubmit(EmploymentVisaCancelationVO employeVisaCancelationVO, String appId) throws Exception{
		return storeToDb(employeVisaCancelationVO, appId, true);
	}
	
	private AppSaveResponseVO storeToDb(EmploymentVisaCancelationVO employmentVisaCancelationVO, String appId, boolean isResubmit) throws Exception{
		AppSaveResponseVO appSaveResponseVO = new AppSaveResponseVO();
		Integer incident = null; 
		
		UserVO userVO =  employmentVisaCancelationVO.getUserVO();
		User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
		
		String compLicNo = tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(user.getClient().getCTrakheesId());
		if(userVO.isAdmin()){
			buisnessValidationManager.validateOnlineEmpVisaTerminationData(compLicNo);
			gsInfoManager.isRequestExist(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION,employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO().getEvcEmployeeId(), null);
			if(!gsEmployeeDetailsManager.validateEmployee(employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO().getEvcEmployeeId(), 
					compLicNo)){
				throw new InvalidEmpIdException();
			}
		}
		
		AppMetaDataFactory appMetaDataFactory = null;
		String clientRefNo = null;
		boolean backOfficeRejectflag=false;
		if(isResubmit){
			AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(appId, 
					Process.PROCESS_EMPLOYMENT_VISA_CANCELATION, Steps.RESUBMIT, user.getClientId());
			appMetaDataFactory = AppMetaDataFactory.createReSubmitFactory(appMetaData);
			if(appMetaData.getStatusCode()==5){
				backOfficeRejectflag=true;
			}
			if(userVO.isAdmin() && !backOfficeRejectflag){
				clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION);
				appMetaData.setClientRefNo(clientRefNo);
			}
		} else {
			if(userVO.isAdmin()){
				clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION);
			}
			appMetaDataFactory = AppMetaDataFactory.createSubmitFactory(clientRefNo);
		}
		
		AppMetaData appMetaData = appMetaDataFactory.getAppMetaData();
		
		Long serviceCode =  ServiceMaster.EV_CANCELATION;
		appMetaData.setServiceCode(serviceCode);
		
		if(userVO.isAdmin()){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN);
		}else if (!isResubmit) {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_INITIATED);
		} else {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_RESUBMITED);
		}
		
		appMetaData.setProcessCode(Process.PROCESS_EMPLOYMENT_VISA_CANCELATION);
		appMetaData.setUserId(user.getUId());
		appMetaData.setClientId(user.getClientId());
		appMetaData.setApplicationDate(new Date());
		if(!isResubmit || appMetaData.getApplicationId()==null){
			appMetaDataDOM.add(appMetaData);
		}
		
		
		if(isResubmit){
			taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());
		}
		
		if(!userVO.isAdmin()){	
			taskAndNotificationsManager.sendTask(appMetaData, TaskMaster.__ADMIN_APPROVE_TASK_CODE);
		}
		
		EmploymentVisaCancel employmentVisaCancel = appMetaDataFactory.getEmploymentVisaCancel();
		getMapper().map(employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO(), employmentVisaCancel);
		employmentVisaCancel.setAppMetaData(appMetaData);
		employmentVisaCancelDOM.add(employmentVisaCancel);
		appMetaData.setEmploymentVisaCancel(employmentVisaCancel);
		
		String referenceNumber = appMetaData.getApplicationId().toString();
		if(!userVO.isAdmin() && !backOfficeRejectflag){
			appMetaData.setClientRefNo(referenceNumber);
		}
		
		appMetaData.setTempFileStorages(fileStorageManager.storeFiles(appMetaData, employmentVisaCancelationVO.getFileVOList(), 
				appMetaDataFactory.getTempFileStoragesMap()));
		
		//add list of param here
		if(userVO.isAdmin()){
			 String fnpServiceCode = employmentVisaCancelationVO.getFnpServiceCode();
			 FNPPaymentAdviceVO fnpPaymentAdviceVO = 
					 fnpManager.generatePayment(appMetaData.getApplicationId(), userVO.getUsername(), fnpServiceCode, 
							 employmentVisaCancelationVO.getFnpParams(),null,appMetaData.getClientRefNo());
			 appMetaData.setPaymentAdviceNo(fnpPaymentAdviceVO.getPaymentAdviceNumber());
			 appMetaData.getTempFileStorages().add(fnpPaymentAdviceVO.getStoredPaymentAdvice());
		}
		
		EmploymentVisaCancelationAppInfoVO employmentVisaCancelationAppInfoVO = new EmploymentVisaCancelationAppInfoVO();
		getMapper().map(employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO(), employmentVisaCancelationAppInfoVO);
		employmentVisaCancelationAppInfoVO.setG_ApplicationDate(appMetaData.getApplicationDate());
		
		/*add action comment*/
		ReviewComments reviewComments = new ReviewComments();
		reviewComments.setApplicationId(appMetaData.getApplicationId());
		reviewComments.setStatusCode(appMetaData.getStatusCode());
		reviewComments.setRcUserName(user.getUUsername());
		reviewComments.setRcComments(employmentVisaCancelationVO.getComment());
		reviewCommentsDOM.add(reviewComments);
		
		/*Send notification*/
		//if(!userVO.isAdmin()){
			NotificationVO notificationVO = new NotificationVO();
			notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
			Map<Object, Object> parameters = new HashMap<Object, Object>();
			parameters.put("comments", employmentVisaCancelationVO.getComment());
			notificationVO.setParameters(parameters);
			taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		//}

		//launch workflow
		if(appMetaData.getWfIncidentId() == null){
			if(userVO.isAdmin()){
				LaunchIncedentVO launchIncedentVO = new LaunchIncedentVO();
				TerminateEVSubmGVarVO terminateEVSubmGVarVO = new TerminateEVSubmGVarVO();
				terminateEVSubmGVarVO.setG_ApplicationID(referenceNumber);
				terminateEVSubmGVarVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				terminateEVSubmGVarVO.setG_EmployeeType(UltimusConstants.EMPLOYEE_TYPE_RP);
				terminateEVSubmGVarVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				terminateEVSubmGVarVO.setG_RPCancellationMethod(employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO()
						.getEvcCancelform());
				try{		
					incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), launchIncedentVO, 
							terminateEVSubmGVarVO, employmentVisaCancelationAppInfoVO);
				}catch (Exception e) {
					e.printStackTrace();
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
					throw new UltimusAppException(e);
				}
				appMetaData.setWfIncidentId(incident.toString());
				appMetaData.setWfInitiatedBy(user.getUUsername());
			}
		} else{
			 incident = Integer.parseInt(appMetaData.getWfIncidentId());
			
			CompleteStepVO completeStepVO = new CompleteStepVO();
			completeStepVO.setStrStepName(UltimusConstants.RESUBMIT_ONLINE_APPLICATION_STEP);
			completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
			completeStepVO.setnIncidentNumber(incident);
			
			
			//:TODO put code for WF inwocation for resubmit
			TerminateEVReSubmGVarVO terminateEVReSubmGVarVO = new TerminateEVReSubmGVarVO();
			terminateEVReSubmGVarVO.setG_ApplicationID(referenceNumber);
			terminateEVReSubmGVarVO.setG_EmployeeType(UltimusConstants.EMPLOYEE_TYPE_RP);
			if(!userVO.isAdmin()){
				terminateEVReSubmGVarVO.setG_ApplicationResubmittedBy(EmployeeType.EMPLOYEE.getEmployeeType());
			}else{
				terminateEVReSubmGVarVO.setG_ApplicationResubmittedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
			}
			terminateEVReSubmGVarVO.setG_RPCancellationMethod(employmentVisaCancelationVO.getEmploymentVisaCancelationDetailsVO()
					.getEvcCancelform());
			terminateEVReSubmGVarVO.setG_ApplicationResubmitDecision(ApplicationResubmitDecision.RESUBMITTED.getResubmitDecision());
			
			try{		
				genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, terminateEVReSubmGVarVO, 
						employmentVisaCancelationAppInfoVO);
			}catch (Exception e) {
				e.printStackTrace();
				if(userVO.isAdmin()){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
				}
				throw new UltimusAppException(e);
			}
		}
		
		/*
		 * transfer request to GS
		 */
			transferDataToGS(appMetaData, userVO, compLicNo);
		/*
		 * end of transfer
		 */
		
		if(isResubmit){
			appMetaDataDOM.update(appMetaData);
		} else {
			appMetaDataDOM.updateAndAddEtks(appMetaData);
		}
		
		appSaveResponseVO.setReferenceNo(appMetaData.getClientRefNo());
		appSaveResponseVO.setIncidentNo(appMetaData.getWfIncidentId());
		return appSaveResponseVO;
	}
	
	@Transactional
	public void submitExitDocument(SubmitExitPaperVO submitExitPaperVO) throws Exception{
		UserVO userVO =  submitExitPaperVO.getUserVO();
		User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
		
		AppMetaData appMetaData = appMetaDataDOM.getPlainAppMetaDataById(submitExitPaperVO.getAppId());
		
		if(appMetaData==null || !appMetaData.getClientId().equals(user.getClientId())){
			throw new BadAppException("Bad App");
		}
		
		taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());
		appMetaData.setStatusCode(ApplicationStatus.STATUS_EXIT_PAPER_SUBMITED);
		appMetaDataDOM.update(appMetaData);
		
		FileVO exitdoc = submitExitPaperVO.getExitPaper();
		
		Long onlineFileId = fileStorageManager.storeFileInNewTransaction(exitdoc, appMetaData.getApplicationId())
				.getId();
		exitdoc.setId(onlineFileId);
		exitdoc.setApplicationId(appMetaData.getApplicationId());
		
		fileStorageManager.transferToDotNet(exitdoc);
		
		BaseGVariablesVO baseGVariablesVO = new BaseGVariablesVO();
		baseGVariablesVO.setG_ApplicationID(appMetaData.getClientRefNo());
		
		CompleteStepVO completeStepVO = new CompleteStepVO();
		completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
		completeStepVO.setnIncidentNumber(new Integer(appMetaData.getWfIncidentId()));
		completeStepVO.setStrStepName(UltimusConstants.UPLOAD_EXIT_PAPER_STEP);
		
		genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, baseGVariablesVO);
		
	}
}
